﻿@using ServiceStack.Text
@using System.Collections.Concurrent
@inject IJSRuntime JS

@if (!string.IsNullOrEmpty(contents))
{
    if (Title != null)
    {
        <h2 class="mt-8 mb-4 text-2xl font-semibold text-gray-900 dark:text-gray-100 flex justify-between items-center">
            <div>@Title</div>
            @if (IncludeGithubLink && Path != null)
            {
                <a class="mr-2" href=@GalleryCodeBaseUrl.CombineWith(Path) title="View on Github">
                    <svg class="w-5 h-5" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" transform="scale(64)" fill="#1B1F23"></path>
                    </svg>
                </a>
            }
        </h2>
    }

    <div class="example-code m-4 w-full" style="background-color:#1E1E1E">
        <pre class="w-full"><code class=@CssUtils.ClassNames(Language, "rounded block w-full p-4 overflow-x-auto")>@contents</code></pre>
    </div>
}

@code {
    [Parameter] public string? Title { get; set; }
    [Parameter] public string? Path { get; set; }

    [Parameter] public string? SourceCode { get; set; }
    [Parameter] public string Language { get; set; } = "cshtml-razor";
    [Parameter] public bool IncludeBreadcrumbs { get; set; }
    [Parameter] public bool IncludeGithubLink { get; set; } = true;

    static ConcurrentDictionary<string, string> Cache = new();

    string? contents = "";

    public static string GalleryCodeBaseUrl { get; set; } = "https://github.com/NetCoreApps/BlazorGallery/tree/main/MyApp/Components/Pages";

    public static string GalleryPreviewBaseUrl { get; set; } = "https://raw.githubusercontent.com/NetCoreApps/BlazorGallery/main/MyApp/Components/Pages";

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (firstRender)
        {
            if (string.IsNullOrEmpty(contents))
            {
                if (!string.IsNullOrEmpty(SourceCode))
                {
                    contents = SourceCode;
                }
                else if (!Cache.TryGetValue(Path!, out contents))
                {
                    Cache[Path!] = contents = await DownloadPageContentsAsync(Path!);
                }
                StateHasChanged();
            }
        }
        await JS.InvokeVoidAsync("hljs.highlightAll");
    }

    public async Task<string> DownloadPageContentsAsync(string relativeUrl)
    {
        var pageUrl = GalleryPreviewBaseUrl.CombineWith(relativeUrl);
        var contents = await pageUrl.GetStreamFromUrlAsync(requestFilter: req => req.With(x => x.UserAgent = "ServiceStack.Blazor"));
        var sb = StringBuilderCache.Allocate();
        var skippedDirectives = false;
        var inBreadcrumbs = false;
        foreach (var line in contents.ReadLines())
        {
            if (!skippedDirectives && line.StartsWith("@"))
                continue;
            else
                skippedDirectives = true;

            var trimmedLine = line.Trim();
            if (trimmedLine.StartsWith("<ExampleCode"))
                continue;

            if (!IncludeBreadcrumbs)
            {
                if (trimmedLine.StartsWith("<Breadcrumbs"))
                {
                    inBreadcrumbs = true;
                    continue;
                }
                else if (trimmedLine.StartsWith("</Breadcrumbs>"))
                {
                    inBreadcrumbs = false;
                    continue;
                }

                if (inBreadcrumbs)
                    continue;
            }

            sb.AppendLine(line);
        }
        return StringBuilderCache.ReturnAndFree(sb).Trim();
    }
}
